//This include is needed for the general 628 function call stuff
#include <system.h>
#include "usart.h"
#include "crc16.h"
//#define SIMULATOR
//#define _2MHZ

#ifdef _PIC16F874
  #define TMR0IF T0IF
  #define TMR0IE T0IE
#endif

#ifdef _2MHZ
	#pragma CLOCK_FREQ 2000000
	#pragma DATA _CONFIG1, _LVP_OFF & _BODEN_ON & _MCLR_OFF & _WDT_ON & _PWRTE_ON & _EXTCLK //0x3F47
#else
	#pragma CLOCK_FREQ 8000000
	#pragma DATA _CONFIG1, _LVP_OFF & _BODEN_ON & _MCLR_OFF & _WDT_ON & _PWRTE_ON & _INTRC_IO //0x3F54
//	#pragma DATA _CONFIG1, _LVP_OFF & _BODEN_ON & _MCLR_OFF & _WDT_ON & _PWRTE_ON & _XT_OSC //0x3F46
#endif

//pump control flags (flags)
#define T0READY			0
#define SAMPLEREADY		1
#define ADREADY			2
#define LOW_LEVEL		3
#define PUMP_RAN_DRY		4
#define IN_RECOVERY		5
#define PUMP_READY		6
#define PUMP_ON			7

//user input control flags (ctl_flags)
#define DISPLAY_ON		0
#define BUTTON_DOWN		1
#define RESET_COUNTDOWN		2
#define FIRST_PRESS		3
#define GREY			4 // Set if the rotary switch has changed state and is ready to read
#define CLOCKWISE		5 // Setif the rotary switch direction was clockwise
#define MENU_LVL		6
#define TURN_PUMP_ON		7

//////////////////////////
#define _T0READY		(1<<T0READY)
#define _SAMPLEREADY		(1<<SAMPLEREADY)
#define _ADREADY		(1<<ADREADY)
#define _DISPLAY_ON		(1<<DISPLAY_ON)
#define _BUTTON_DOWN		(1<<BUTTON_DOWN)
#define _RESET_COUNTDOWN	 (1<<COUNT_DOWN)
#define _FIRST_PRESS		(1<<FIRST_PRESS)
#define _IN_RECOVERY		(1<<IN_RECOVERY)
#define _PUMP_READY 		(1<<PUMP_READY)
#define _PUMP_ON 		(1<<PUMP_ON)
/////////////////////////

#define BUTTON_PRESS	2

#define _GREY_OFFSET    6    // (port_b >> _GREY_OFFSET) & 0x03

#define DISPLAY_TIME	0x10000-600

//EEPROM Locations
#define MIN_COUNT 0x00		//16 bits (A/D reading at empty tank)
#define MAX_COUNT 0x02		//16 bits (A/D reading at full tank)
#define TANK_SIZE 0x04		//16 bits (# of gallons in tank)
#define THRESHOLD 0x06		//16 bits (turn on when tank falls below this # of gallons)
#define LOWLVL_WARN 0x08	//16 bits (send warning flag to receiver when tank falls below this # of gallons)
#define RUN_TIME  0x0A		//8 bits  (# of minutes to run pr hour)
#define RUNDRY_TIME 0x0B	//8 bits  (# of minutes to wait in recovery if the tank runs dry)
#define _8BITVALS RUN_TIME

//EEPROM Initial Values
#if 1
//#pragma doesn't support #defined addresses, so we can't use the above defines
#pragma DATA 0x2100,	0XB8, 0x0B	//3000
#pragma DATA 0x2102,	0x20, 0xCB	//50000
#pragma DATA 0x2104,	0xDC, 0x05	//1500
#pragma DATA 0x2106,	0xB0, 0x04	//1200
#pragma DATA 0x2108,	0x20, 0x03	//800
#pragma DATA 0x210A,	0x5A		//90
#pragma DATA 0x210B,	0x37		//55
#endif

#define timer0_reload_value 0

#ifndef test_bit 
#define test_bit(x,y) (x&(1<<y))
#endif
/* ./build_pragma.pl menu.h */
#include "menu.h"

char tmp=0;
char flags, ctl_flags;
char tock;
char t1_overflow;
char t2_overflow1;
unsigned short t2_overflow2;
unsigned short t2_overflow3;

char menu_item;
unsigned short menu_sel;
unsigned short orig_val;
unsigned short max_count;
unsigned short step;

unsigned short max_lvl_count;
unsigned short min_lvl_count;

unsigned short tank_size;
unsigned short threshold;
unsigned short lowlvl_warn;
unsigned short stop_depth;

char on_time;
char off_time;
char max_ontime;
char max_offtime;
char rundry_time;

unsigned short depth;
unsigned char count_per_gal;
unsigned short buf_portb;

#define BAUD_SLOW 103 //1200 bps
#define BAUD_FAST 12 //9600 bps
#ifndef SIMULATOR
	#define PowerUpDisplay() { drainTx(); spbrg=BAUD_FAST; set_bit(portb, 0); sendChar(0x7C); sendChar(0x01); \
								delay_ms(10); sendChar(0xFE); sendChar(0x0C);}
	#define PowerDownDisplay() { sendChar(0xFE); sendChar(0x08); delay_ms(5); sendChar(0x7C); sendChar(0x02);}
	#define SetPosLine2() {sendChar(0xFE); sendChar(0x80|64);} //second line of display
	void ClearScreen()
	{
		sendChar(0xFE);
		sendChar(0x01);
		delay_ms(5);
	}
#else
	#define PowerUpDisplay() { set_bit(portb, 0); sendChar('O'); sendChar('n'); sendChar('\n');}
	#define PowerDownDisplay() { sendChar('O'); sendChar('f'); sendChar('f'); sendChar('\n');}
	#define ClearScreen() {sendChar('C'); sendChar('l'); sendChar('e'); sendChar('a'); sendChar('r'); sendChar('\n');}
	#define SetPosLine2() {sendChar('\n');}
#endif

#define button_press() (! test_bit(buf_portb, BUTTON_PRESS))
unsigned char old_AB;
void update_grey_state()
{
    static const char enc_states[16] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0};
    unsigned char new_val = ( buf_portb >> _GREY_OFFSET) & 0x03;
    old_AB = old_AB << 2;       // remember previous state
    old_AB = old_AB | new_val;  // add current state
    unsigned char val = enc_states[( old_AB & 0x0f )];
    if (val != 0) {
        if (new_val == 0 || new_val == 3) {
            set_bit(ctl_flags, GREY);
        } else {
            clear_bit(ctl_flags, GREY);
            if (val > 0) {
                set_bit(ctl_flags, CLOCKWISE);
            } else {
                clear_bit(ctl_flags, CLOCKWISE);
            }
        }
    }
}

void write_eeprom(char addr, char data)
{
	char int_on;
	while(test_bit(eecon1, WR))
		;
	eeadr=addr;
	eedata=data;
	clear_bit(eecon1, EEPGD);
	int_on=(test_bit(intcon, GIE));
	clear_bit(intcon, GIE);
	set_bit(eecon1, WREN);
	eecon2=0x55;
	eecon2=0xaa;
	set_bit(eecon1, WR);
	if(int_on)
		set_bit(intcon, GIE);
	clear_bit(eecon1, WREN);
}
char read_eeprom( char addr )
{
	char ret;
    //Read flash
	while(test_bit(eecon1, WR))
		;
    eeadr = addr;
	clear_bit(eecon1, EEPGD);
    set_bit( eecon1, RD );
    asm movf _eedata, W
    asm movwf _ret;
    return(ret);
}
#ifndef SIMULATOR
void sendFromRom(char val)
{
	char addr;
	char i;
	if(test_bit(ctl_flags, MENU_LVL) && val != 0)
		val+=MENU_2;
	else if(val==MENU_ON) {
		if(test_bit(flags, PUMP_ON)) {
			clear_bit(ctl_flags, TURN_PUMP_ON);
			val=MENU_OFF;
		} else {
			set_bit(ctl_flags, TURN_PUMP_ON);
		}
	}
	val=val<<3;
	addr=ROM_ADDR;
	addr+=val;
	eeadrh=ROM_ADDR>>8;
	for(i=0;i<8;i++) {
		eeadr=addr;
		set_bit(eecon1, EEPGD);
		set_bit(eecon1, RD);
		nop();
		nop();
		sendChar(eedata& 0x7F);
		val=eedath<<1;
		if(test_bit(eedata,7))
			val |= 0x01;
		val=val&0x7F;
		sendChar(val);
		addr++;
	}
}
#else
void sendFromRom(char val)
{
	char addr;
	char val;
	char i;
	if(test_bit(ctl_flags, MENU_LVL) && val != 0)
		val+=MENU_2;
	else if(val==MENU_ON) {
		if(test_bit(flags, PUMP_ON)) {
			clear_bit(ctl_flags, TURN_PUMP_ON);
			val = MENU_OFF;
		} else {
			set_bit(ctl_flags, TURN_PUMP_ON);
		}
	}
	val=val<<4;
	addr=ROM_ADDR;
	addr+=val;
	for(i=0;i<16;i++) {
		sendChar(read_eeprom(addr));
		addr++;
	}
}
#endif
void ShowValue()
{
	char i;
	SetPosLine2();
	if(! menu_item) {
		sendFromRom(menu_sel);
	} else {
		for(i=0;i<16;i++)
			sendChar(' ');
		SetPosLine2();
		sendDecimalShort(orig_val);
		sendChar(' ');
		sendDecimalShort(menu_sel);
	}
}

unsigned short read_short_eeprom( char addr )
{
	return((read_eeprom(addr+1)<<8)|read_eeprom(addr));
}

void check_run_dry()
{
	tock=0;
	while(tock < 2) {
		if(!test_bit(porta, 1)) {
			clear_bit(flags, PUMP_RAN_DRY);
			return;
		}
		clear_wdt();
	}
	set_bit(flags, PUMP_RAN_DRY);
}
	
void start_pump()
{

	set_bit(flags, PUMP_ON);
	set_bit(flags, IN_RECOVERY);
	clear_bit(flags, PUMP_READY);
	clear_bit(flags, PUMP_RAN_DRY);
	on_time=0;
	off_time=0;
	//now turn pump on
	set_bit(porta, 2);
}

void stop_pump()
{
	check_run_dry();
	clear_bit(flags, PUMP_ON);
	//now turn pump off
	clear_bit(porta, 2);
}

void debounce(void)
{
#ifndef SIMULATOR
	delay_ms(5);
#endif
}

void compute_on_off_times()
{
	if(max_ontime > 60)
		max_ontime=60;
	max_offtime=60-max_ontime;
}

void compute_units_per_gal(void)
{
	count_per_gal=(max_lvl_count - min_lvl_count) / tank_size;
	stop_depth=tank_size-(tank_size/30);			//leave ~3% gap
}

void show_status()
{
	ClearScreen();
	if(test_bit(flags, PUMP_RAN_DRY)) {
		sendChar('D');
		sendChar('r');
		sendChar('y');
	} else {
		sendChar('O');
		if(test_bit(flags, PUMP_ON))
			sendChar('n');
		else {
			sendChar('f');
			sendChar('f');
		}
	}
	sendChar(' ');
	sendDecimalByte(on_time);
	sendChar('/');
	sendDecimalByte(max_ontime);
	sendChar(' ');
	sendDecimalByte(off_time);
	sendChar('/');
	if(test_bit(flags, PUMP_RAN_DRY))
		sendDecimalByte(rundry_time);
	else
		sendDecimalByte(max_offtime);
	SetPosLine2();
	sendDecimalShort(depth);
	sendChar('-');
	sendDecimalByte(adresh);
}

void send_status()
{
	char tmp;
#define HI_CRC 0xb7
#define LO_CRC 0x74
//	return;
	drainTx();
	clear_bit(portb, 0);
	spbrg=BAUD_SLOW;
#ifdef USE_CRC
	crc_hi= HI_CRC;	//precalculated based on header
	crc_lo= LO_CRC;
	UpdateCrc(on_time);
	UpdateCrc(max_ontime);
	UpdateCrc(off_time);
	UpdateCrc(rundry_time);
	UpdateCrc(depth>>8);
	UpdateCrc(depth&0xff);
	UpdateCrc(adresh);
	UpdateCrc(flags);
#endif
/*
	sendManchesterByte(0xF0);  //start byte
	sendManchesterByte(0xF0);  //start byte
	sendManchesterByte(0xF0);  //start byte
	sendManchesterByte(0x50);  //SNAP HDB2
	sendManchesterByte(0x48);  //SNAP HDB1
	sendManchesterByte(0x02);  //SNAP DAB1
	sendManchesterByte(0x01);  //SNAP SAB1
*/
	sendManchesterByte(0x00); //sync (sends 0xAA, 0xAA) 
	sendManchesterByte(0x00); //sync (sends 0xAA, 0xAA) 
	sendManchesterByte(0x00); //sync (sends 0xAA, 0xAA) 
	sendManchesterByte(0xA5); //preamble (0x99, 0x66)
	sendManchesterByte(0x1F); //preamble (0x55, 0xA9)
	sendManchesterByte(on_time);
	sendManchesterByte(off_time);
	sendManchesterByte(max_ontime);
	sendManchesterByte(rundry_time);
	sendManchesterByte(depth>>8);
	sendManchesterByte(depth&0xff);
	sendManchesterByte(adresh);
	sendManchesterByte(flags);
#ifdef USE_CRC
	sendManchesterByte(crc_hi);
	sendManchesterByte(crc_lo);	
#endif
}

unsigned int Round(unsigned int value, unsigned int round)
{
   unsigned int mod = value % round;
   if(mod > (round>>1))
     return value+(round-mod);
   return  value-mod;
}
 
void get_input(void)
{
	if(test_bit(ctl_flags, BUTTON_DOWN))
	{
		if(! button_press())
		{
			debounce();
			clear_bit(ctl_flags, BUTTON_DOWN);
			clear_bit(ctl_flags, GREY);
		}
	}
	else if(! test_bit(ctl_flags, DISPLAY_ON))
	{
		if(button_press())
		{
			debounce();
			set_bit(ctl_flags, BUTTON_DOWN);
			set_bit(ctl_flags, RESET_COUNTDOWN);
			set_bit(ctl_flags, FIRST_PRESS);
			PowerUpDisplay();
			set_bit(ctl_flags, DISPLAY_ON);
			show_status();
		}
		else if(t2_overflow3==0)
		{
			t2_overflow3++;
			PowerDownDisplay();
		}
	}
	else if(test_bit(ctl_flags, FIRST_PRESS))
	{
		if(button_press())
		{
			set_bit(ctl_flags, RESET_COUNTDOWN);
			debounce();
			clear_bit(ctl_flags, FIRST_PRESS);
			set_bit(ctl_flags, BUTTON_DOWN);
			ClearScreen();
			//sendFromRom(1);
			clear_bit(ctl_flags, MENU_LVL);
			menu_item=0;
			menu_sel=0;
			max_count=3;
			step=1;
			ShowValue();
		}
	}
	else if(test_bit(ctl_flags, GREY))
	{
		set_bit(ctl_flags, RESET_COUNTDOWN);
		if(test_bit(ctl_flags, CLOCKWISE))
		{
			if(menu_sel < max_count-step) 
				menu_sel += step;
			else
				menu_sel = max_count;
		} else {
			if(menu_sel > step)
				menu_sel -= step;
			else
				menu_sel = 0;
		}
		clear_bit(ctl_flags, GREY);
		ShowValue();
	}
	else if(button_press())
	{
		char offset;
		set_bit(ctl_flags, RESET_COUNTDOWN);
		if(test_bit(ctl_flags, MENU_LVL)) {
			switch(menu_item) {
				case MENU_MAXLVL - MENU_2:
					//set max water level
					offset=MAX_COUNT;
					max_lvl_count=menu_sel;										
					break;
				case MENU_MINLVL - MENU_2:
					offset=MIN_COUNT;
					//set min water level
					min_lvl_count=menu_sel;
					break;
				case MENU_TANKSIZE - MENU_2:
					offset=TANK_SIZE;
					//set gallons in tank
					tank_size=menu_sel;
					break;
				case MENU_MAXONTIME - MENU_2:
					//set maximum runtime per hour (min)
					offset=RUN_TIME;
					break;
				case MENU_THRESHOLD - MENU_2:
					//set max gph
					offset=THRESHOLD;
					threshold=menu_sel;
					break;
				case MENU_LOWLVLWARN - MENU_2:
					//set low-level warning (gal)
					offset=LOWLVL_WARN;
					lowlvl_warn = menu_sel;
					break;
				case MENU_RUNDRY - MENU_2:
					//set rundry time (min)
					offset=RUNDRY_TIME;
					rundry_time = menu_sel & 0xff;
					break;
			}
			if(menu_item)
			{
				write_eeprom(offset, menu_sel & 0xff);
				if(offset<_8BITVALS)
					write_eeprom(offset+1, menu_sel >> 8);
				compute_units_per_gal();
				compute_on_off_times();
				clear_bit(ctl_flags, MENU_LVL);
				menu_sel=1;
			} else {
				//menu
				menu_item=menu_sel;
				switch(menu_sel) {
					case MENU_PREV:
						//Go up one level
						set_bit(ctl_flags, FIRST_PRESS);
						break;
					case MENU_MAXLVL - MENU_2:
						 //set max water level
					case MENU_MINLVL - MENU_2:
						//set min water level
						while(!test_bit(flags, T0READY))
							;
						if(menu_sel==1)
							orig_val=max_lvl_count;
						else
							orig_val=min_lvl_count;
						step=500;
						menu_sel=Round((tmr1h<<8)+tmr1l, 500);
						max_count=0xffdc;
						break;
					case MENU_TANKSIZE - MENU_2:
						//set gallons in tank
						orig_val=tank_size;
						menu_sel=tank_size;
						max_count=10000;
						step=100;
						break;
					case MENU_MAXONTIME - MENU_2:
						//set maximum runtime per hour (min)
						menu_sel=read_short_eeprom(RUN_TIME);
						orig_val=menu_sel;
						max_count=60;
						step=1;
						break;
					case MENU_THRESHOLD - MENU_2:
						//set threshold (gallons)
						menu_sel=threshold;
						orig_val=menu_sel;
						max_count=tank_size;
						step=100;
						break;
					case MENU_LOWLVLWARN - MENU_2:
						//set low-level warning (gal)
						menu_sel=lowlvl_warn;
						orig_val = menu_sel;
						max_count = tank_size;
						step=100;
						break;
					case MENU_RUNDRY - MENU_2:
						//set rundry time (min)
						menu_sel=rundry_time;
						orig_val=menu_sel;
						step=5;
						break;
				}
				if(menu_item) {
					set_bit(ctl_flags, BUTTON_DOWN);
					ClearScreen();
					sendFromRom(menu_item);
					ShowValue();
				}
			}
		}
		if(! test_bit(ctl_flags, MENU_LVL)) {
			set_bit(ctl_flags, BUTTON_DOWN);
			ClearScreen();
			switch(menu_sel) {
				case MENU_ON:  //Also MENU_OFF
					if(test_bit(ctl_flags, TURN_PUMP_ON))
						start_pump();
					else
						stop_pump();
					goto top_menu;
				case MENU_RUN_TIL_FULL:
					max_offtime = -1;
					start_pump();
					goto top_menu;
				case MENU_PREV:
top_menu:
					set_bit(ctl_flags, FIRST_PRESS);
					show_status();
					break;
				case MENU_SETTING:
					set_bit(ctl_flags, MENU_LVL);
					max_count=MENU_LAST - MENU_2;
					menu_item=0;
					menu_sel=0;
					step=1;
					ShowValue();
					break;
			}
		}
	}
}


//Declare all C function protoypes
//void delay_ms(uns8);

void interrupt()
{
//	porta=tmp;
//	tmp^=0x04;
    if (test_bit(intcon, TMR0IF)) {  //Timer 0 overflow
		if(!test_bit(flags, T0READY)) {
			clear_bit(t1con, TMR1ON);   //shutoff timer1
			set_bit(flags, T0READY);
		}
		clear_bit(intcon, TMR0IE);  //disable all future interrupts
		clear_bit(intcon, TMR0IF);  //clear interrupt flag
	}
	if (test_bit(pir1, TMR1IF)) {
		t1_overflow++;
		clear_bit(pir1, TMR1IF);
	}
	if (test_bit(pir1, TMR2IF)) {
		tock++;
		// Count number of overflows for sample rate (152*32.7ms = 5 sec)
		if(152 == ++t2_overflow1) {
			// Clear to start again
			//Schedules timer0 to start water level measurement, also printf()
			t2_overflow1 = 0;
			set_bit(flags, SAMPLEREADY);
		}
		// Count number of overflows for 1 minute (1831*32.7ms = 5 sec)
		if(1831 == ++t2_overflow2) {
			t2_overflow2=0;
			if(test_bit(flags, PUMP_ON))
				on_time++;
			else
				off_time++;
		}
		if(test_bit(ctl_flags, DISPLAY_ON))
		{
			if(test_bit(ctl_flags, RESET_COUNTDOWN))
			{
				clear_bit(ctl_flags, RESET_COUNTDOWN);
				t2_overflow3=DISPLAY_TIME;
			} else {
				if(0==++t2_overflow3)
					clear_bit(ctl_flags, DISPLAY_ON);
			}
		}
		clear_bit(pir1, TMR2IF);
	}
	if (test_bit(pir1, ADIF)) {
		set_bit(flags, ADREADY);
		clear_bit(pir1, ADIF);
	}
	if (test_bit(intcon, RBIF)) {
		//must test GREY after portb, otherwise the interrupt won't reset
                buf_portb = portb;
                update_grey_state();
		clear_bit(intcon, RBIF);
	}
}

//Start the main - this is the very first stuff the PIC will run
void main()
{
#ifndef _PIC16F874
	osccon=0x70;
	ansel=0x09;
#endif
	wdtcon=0xf7; //Watchdog timeout=~2sec
	clear_wdt();
    trisa = 0x1b ; //Tri-State Buffer - Telling the pic you want the pin to be output or input
	porta=0x00;
	trisb=0xfe;
	portb=0xff;

	adcon1=0x60; //left-justify, 16Tosc, Vref+
	adcon0=0x41; //select AN0,  16Tosc,A/D on

	t1_overflow=0;
	t2_overflow1=0;
	t2_overflow2=0;
	t2_overflow3=1;
	flags = 0;
	ctl_flags=0;
	tmr0=timer0_reload_value;
	on_time=0;
	off_time=0;
	old_AB = 0;
	set_bit(flags, PUMP_READY);
	tank_size=read_short_eeprom(TANK_SIZE);
	max_lvl_count=read_short_eeprom(MAX_COUNT);
	min_lvl_count=read_short_eeprom(MIN_COUNT);
	threshold=read_short_eeprom(THRESHOLD);
	lowlvl_warn=read_short_eeprom(LOWLVL_WARN);
	rundry_time=read_eeprom(RUNDRY_TIME);
	compute_units_per_gal();
	compute_on_off_times();
#ifdef _2MHZ
	set_bit(txsta, BRGH); //2Mhz clock: brgh=1, spbrg=12 --> 9600bps
	t2con=0x7d; //Timer2 enables, 4:1 prescaler, 16:1 postscaler
	t1con=0x14; //Timer1 internal timer, 2:1 prescaler,
#else
	t2con=0x7f; //Timer2 enabled, 16:1 prescaler, 16:1 postscaler
	t1con=0x34; //Timer1 internal timer, 8:1 prescaler,
#endif

	spbrg=BAUD_FAST; //9600bps
	set_bit(rcsta, SPEN); //enable serial port
	set_bit(txsta, TXEN); //enable transmitter

	option_reg=0x21; //PortB-pullup, Timer0 ext clk, 4-to-1 prescaler, rising edge detect
	set_bit(pie1, TMR1IE);  //enable Timer1 overflow interrupt

	set_bit(pie1, TMR2IE);  //enable Timer1 overflow interrupt
	set_bit(pie1, ADIE);  //enable A/D interrupt
	set_bit(intcon, RBIE); //enable portb interrupt
	set_bit(intcon, PEIE); //enable peripheral interrupts
#ifndef SIMULATOR
	set_bit(porta, 2);
	delay_ms(100);
	delay_ms(100);
	clear_bit(porta, 2);
#endif
	old_AB = (portb >> _GREY_OFFSET) & 0x03;
	ClearScreen();
    //Classic while loop, loops forever
	set_bit(intcon, GIE); //enable interrupts
    while(1)
    {
		t2_overflow1=0;
		t1_overflow=0;
		tmr1h=0;
		tmr1l=0;
		tmr0=timer0_reload_value;
		clear_bit(intcon, TMR0IF);
		set_bit(t1con, TMR1ON);
		set_bit(intcon, TMR0IE);
		set_bit(adcon0, GO_DONE); //start A/D
		while((_SAMPLEREADY | _ADREADY | _T0READY) != (flags & (_SAMPLEREADY | _ADREADY | _T0READY)))
		{
			clear_wdt();
			get_input();
			if(test_bit(flags, PUMP_ON)) {
				if(max_offtime != -1 && (test_bit(flags, PUMP_RAN_DRY) || (on_time > max_ontime && max_offtime != 0))) {
					stop_pump();
				}
			} else {
				if(!test_bit(flags, PUMP_READY)) {
					if(test_bit(flags, PUMP_RAN_DRY))  {
						if(off_time > rundry_time)
							set_bit(flags, PUMP_READY);
					} else if(off_time > max_offtime)
						set_bit(flags, PUMP_READY);
				}
			}
		}
		depth=(tmr1h<<8)+tmr1l;
		if(t1_overflow)
			depth=max_lvl_count;
		if(depth > min_lvl_count) {
			depth-=min_lvl_count;
			depth=depth/count_per_gal;
		} else {
			depth = 0;
		}
		if(test_bit(flags, PUMP_ON)) {
			//time to shut off?
			if(depth > stop_depth) {
				stop_pump();
				clear_bit(flags, IN_RECOVERY);
				if(max_offtime == -1)
					compute_on_off_times();
			}
		} else {
			if(test_bit(flags, PUMP_READY)) {
				//time to turn on?
				if(depth < threshold) {
					start_pump();
				}
			}
		}
		if(depth < lowlvl_warn)
			set_bit(flags, LOW_LEVEL);
		else
			clear_bit(flags, LOW_LEVEL);
		if(test_bit(ctl_flags, DISPLAY_ON)) {
			if(test_bit(ctl_flags, FIRST_PRESS)) {
				show_status();
			}
		} else if(t2_overflow3 != 0) {
			send_status();
		}
		flags&=~(_SAMPLEREADY | _ADREADY | _T0READY);
    }
    //End Main
}

